/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package simhya.simengine.hybrid;

import simhya.model.flat.FlatModel;
import java.util.ArrayList;
import simhya.model.store.Predicate;
import simhya.simengine.odeevents.SwitchingEvent;
import java.util.TreeSet;

/**
 *
 * @author luca
 */
public class PopulationSizePartitionManager extends PartitionManager {
    boolean useAbsoluteValue;

    public PopulationSizePartitionManager(FlatModel model, HybridOdeFunction function, 
            double discrete2continuousThreshold, double continuous2discreteThreshold) {
        super(model, function);
        useAbsoluteValue = false;
        this.addGlobalSwitchingStrategy(model,discrete2continuousThreshold,continuous2discreteThreshold);
    }
    
    public PopulationSizePartitionManager(FlatModel model, HybridOdeFunction function, 
            double discrete2continuousThreshold, double continuous2discreteThreshold,
            boolean useAbsoluteValue) {
        super(model, function);
        this.useAbsoluteValue = useAbsoluteValue;
        this.addGlobalSwitchingStrategy(model,discrete2continuousThreshold,continuous2discreteThreshold);
    }



    private void addGlobalSwitchingStrategy(FlatModel model, double d2cThr, double c2dThr) {
        //implement population watching, with two thresholds on population sizes
        //for each variable, find continuous approx transitions that modify it. 
        //This is the list of transitions depending globally from it.
        int n = model.getStore().getNumberOfVariables();
        for (int i=0;i<n;i++) {
            ArrayList<Integer> list = this.findTransitionsModifyingVariable(model, i);
            if (!list.isEmpty()) {
                String var = model.getStore().getVariablesReference().getName(i);
                Predicate d2cPred, c2dPred;
                if (this.useAbsoluteValue) {
                    d2cPred = model.getStore().addPredicate("abs(" + var + ") >= " + d2cThr);
                    c2dPred = model.getStore().addPredicate("abs(" + var + ") <= " + c2dThr);
                } else {
                    d2cPred = model.getStore().addPredicate(var + " >= " + d2cThr);
                    c2dPred = model.getStore().addPredicate(var + " <= " + c2dThr);
                }
                int id = this.globalEvents.size();
                SwitchingEvent e = new SwitchingEvent(id,numberOfTransitions,c2dPred.convertToFunction(),
                        d2cPred.convertToFunction(),c2dPred,d2cPred,this,false,n);
                this.globalEvents.add(e);
                this.globalAffectedTransitions.add(list);
                TreeSet<Integer> depVars = new TreeSet<Integer>(); 
                depVars.add(i);
                this.dependencyOnVariables.put(e.getId(), depVars);
            }
        }
    }
    
    private ArrayList<Integer> findTransitionsModifyingVariable(FlatModel model, int varId) {
        ArrayList<Integer> list = new ArrayList<Integer>();
        for (Integer i : model.getListOfContinuousTransitionID(true)) {
            if (model.getTransition(i).getUpdatedVariables().contains(varId))
                list.add(i);
        }
        return list;
    }

}
